package utils

import (
	"haiqiu-go-admin/entity/dto"
	"log"
)

const (
	LIKE      = " LIKE CONCAT('%',?,'%')"
	LeftLike  = " LIKE CONCAT('%',?)"
	RightLike = " LIKE CONCAT(?,'%')"
	EQUALS    = " = ? "
	LIMIT     = " LIMIT ?,? "
	SELECT    = " SELECT "
	COUNT     = " COUNT(1) "
	FROM      = " FROM "
	SPACE     = " "
	WHERE     = " WHERE 1=1 "
	SPLIT     = ", "
	VAL       = "?"
	AND       = " AND "
	OR        = " OR "
	IN        = " IN "
	ALL       = " * "
	BETWEEN   = " BETWEEN ? AND ? "
	INSERT    = " INSERT INTO "
	ORDER     = " ORDER BY "
	ASC       = " ASC "
	DESC      = " DESC "
	CUT       = "`"
	NoSet     = "sql: no rows in result set"
)

type Crud interface {
	Count(tableName string) *Wrapper
	List(tableName string, columns string) *Wrapper
	All(tableName string) *Wrapper
	Page(tableName string, pageDto dto.PageDto) *Wrapper
	Insert(tableName string, column string, val ...any) *Wrapper
}

type Wrapper struct {
	TableName     string
	sqlSegment    string
	conditions    string
	page          string
	orderBy       string
	orderByParams []any
	params        []any
	pageParams    []any
	log           string
}

func QueryWrapper() *Wrapper {
	return new(Wrapper)
}

func (wrapper *Wrapper) Count(tableName string) *Wrapper {
	wrapper.sqlSegment = SELECT + COUNT + FROM + "`" + tableName + "`" + SPACE + WHERE
	return wrapper
}

func (wrapper *Wrapper) CountColumn(tableName, column string) *Wrapper {
	wrapper.sqlSegment = SELECT + SPACE + column + SPACE + FROM + "`" + tableName + "`" + SPACE + WHERE
	return wrapper
}

func (wrapper *Wrapper) Eq(columnName string, val any) *Wrapper {
	wrapper.sqlSegment += AND + columnName + EQUALS
	wrapper.params = append(wrapper.params, val)
	return wrapper
}

func (wrapper *Wrapper) EqCondition(condition bool, columnName string, val any) *Wrapper {
	if condition {
		wrapper.sqlSegment += AND + columnName + EQUALS
		wrapper.params = append(wrapper.params, val)
	}
	return wrapper
}

func (wrapper *Wrapper) Between(columnName string, val1 any, val2 any) *Wrapper {
	wrapper.sqlSegment += AND + columnName + BETWEEN
	wrapper.params = append(wrapper.params, val1, val2)
	return wrapper
}

func (wrapper *Wrapper) BetweenCondition(condition bool, columnName string, val1 any, val2 any) *Wrapper {
	if condition {
		wrapper.sqlSegment += AND + columnName + BETWEEN
		wrapper.params = append(wrapper.params, val1, val2)
	}
	return wrapper
}

func (wrapper *Wrapper) Like(columnName string, val any) *Wrapper {
	wrapper.sqlSegment += AND + CUT + columnName + CUT + LIKE
	wrapper.params = append(wrapper.params, val)
	return wrapper
}

func (wrapper *Wrapper) LikeCondition(condition bool, columnName string, val any) *Wrapper {
	if condition {
		wrapper.sqlSegment += AND + columnName + LIKE
		wrapper.params = append(wrapper.params, val)
	}
	return wrapper
}

func (wrapper *Wrapper) LeftLike(columnName string, params any) *Wrapper {
	wrapper.sqlSegment += AND + columnName + LeftLike
	wrapper.params = append(wrapper.params, params)
	return wrapper
}

func (wrapper *Wrapper) LeftLikeCondition(condition bool, columnName string, params any) *Wrapper {
	if condition {
		wrapper.sqlSegment += AND + columnName + LeftLike
		wrapper.params = append(wrapper.params, params)
	}
	return wrapper
}

func (wrapper *Wrapper) RightLike(columnName string, params any) *Wrapper {
	wrapper.sqlSegment += AND + columnName + RightLike
	wrapper.params = append(wrapper.params, params)
	return wrapper
}

func (wrapper *Wrapper) RightLikeCondition(condition bool, columnName string, params any) *Wrapper {
	if condition {
		wrapper.sqlSegment += AND + columnName + RightLike
		wrapper.params = append(wrapper.params, params)
	}
	return wrapper
}

func (wrapper *Wrapper) And() *Wrapper {
	wrapper.sqlSegment += AND
	return wrapper
}

func (wrapper *Wrapper) Or() *Wrapper {
	wrapper.sqlSegment += OR
	return wrapper
}

func (wrapper *Wrapper) In(val []any) *Wrapper {
	if len(val) == 0 {
		return wrapper
	}
	wrapper.sqlSegment += AND + IN + " ( "
	for i, v := range val {
		if i < len(val)-1 {
			wrapper.sqlSegment += VAL + SPLIT + SPACE
			wrapper.params = append(val, v)
		} else {
			wrapper.sqlSegment += VAL + SPACE
			wrapper.params = append(val, v)
		}
	}
	wrapper.sqlSegment += " ) "
	return wrapper
}

func (wrapper *Wrapper) List(tableName string, columns string) *Wrapper {
	wrapper.sqlSegment = SELECT + columns + FROM + "`" + tableName + "`" + SPACE + WHERE
	return wrapper
}

func (wrapper *Wrapper) All(tableName string) *Wrapper {
	wrapper.sqlSegment = SELECT + ALL + FROM + CUT + tableName + CUT + SPACE + WHERE
	return wrapper
}

func (wrapper *Wrapper) GetById(tableName string, id any) *Wrapper {
	wrapper.GetByColumn(tableName, "id", id)
	return wrapper
}

func (wrapper *Wrapper) GetByColumn(tableName string, column string, id any) *Wrapper {
	wrapper.sqlSegment = SELECT + ALL + FROM + CUT + tableName + CUT + SPACE + WHERE + AND + column + SPACE + EQUALS
	wrapper.params = append(wrapper.params, id)
	return wrapper
}

func (wrapper *Wrapper) Page(tableName string, pageIndex, pageSize int64) *Wrapper {
	wrapper.sqlSegment += SELECT + ALL + FROM + CUT + tableName + CUT + SPACE + WHERE
	wrapper.page += LIMIT
	limit := (pageIndex - 1) * pageSize
	offset := pageSize
	wrapper.pageParams = append(wrapper.pageParams, limit, offset)
	return wrapper
}

func (wrapper *Wrapper) PageList(tableName, columns string, pageIndex, pageSize int64) *Wrapper {
	wrapper.sqlSegment += SELECT + columns + FROM + CUT + tableName + CUT + SPACE + WHERE + LIMIT
	limit := (pageIndex - 1) * pageSize
	offset := pageSize
	wrapper.params = append(wrapper.params, limit, offset)
	return wrapper
}

func (wrapper *Wrapper) OrderByAsc(column string) *Wrapper {
	wrapper.OrderBy(column, ASC)
	return wrapper
}

func (wrapper *Wrapper) OrderByDesc(column string) *Wrapper {
	wrapper.OrderBy(column, DESC)
	return wrapper
}

func (wrapper *Wrapper) OrderBy(column, order string) *Wrapper {
	wrapper.orderBy = ORDER + CUT + column + CUT + SPACE + order
	return wrapper
}

func (wrapper *Wrapper) Insert(tableName string, column string, val ...any) *Wrapper {
	wrapper.sqlSegment += INSERT + CUT + tableName + CUT + "( " + column + ") VALUES  ( "
	for i, v := range val {
		if i == len(val)-1 {
			wrapper.sqlSegment += " ? "
			wrapper.params = append(wrapper.params, v)
		} else {
			wrapper.sqlSegment += " ?, "
			wrapper.params = append(wrapper.params, v)
		}
	}
	wrapper.sqlSegment += " ) "
	return wrapper
}

func (wrapper *Wrapper) GetSql() string {
	wrapper.sqlSegment += wrapper.orderBy + wrapper.page
	wrapper.params = append(wrapper.params, wrapper.pageParams...)
	log.Println(wrapper.sqlSegment, wrapper.params)
	return wrapper.sqlSegment
}

func (wrapper *Wrapper) GetVal() []any {
	return wrapper.params
}
